namespace ClassyBlog.DataAccess.Specs.Unit
{
    using System;

    using Machine.Specifications;
    using NSubstitute;

    using DomainObjects;

    [Subject(typeof(LazyPage))]
    public class when_creating_lazy_page_with_null_loader
    {
        private static Exception exception;

        Because of = () => exception =
            Catch.Exception(() => new LazyPage(null));

        It should_throw_exception = () =>
            exception.ShouldBeOfType<ArgumentNullException>();
    }

    public abstract class LazyPageSpec
    {
        protected static IArticleLoader<Page> loader;
        protected static LazyPage page;

        Establish context = () =>
        {
            loader = Substitute.For<IArticleLoader<Page>>();
            page = new LazyPage(loader);
        };
    }

    [Subject(typeof(LazyPage))]
    public class when_page_title_is_accessed_for_first_time : LazyPageSpec
    {
        Because of = () => { var title = page.Title; };

        It should_lazy_load = () => loader.Received().Load(page);
    }

    [Subject(typeof(LazyPage))]
    public class when_page_title_is_set : LazyPageSpec
    {
        Establish context = () =>
        {
            page.Title = "Welcome to classy blog.";
            loader.ClearReceivedCalls();
        };

        Because of = () => { var title = page.Title; };

        It should_not_lazy_load = () => loader.DidNotReceive().Load(page);
    }

    [Subject(typeof(LazyPage))]
    public class when_page_meta_keywords_is_accessed_for_first_time :
        LazyPageSpec
    {
        Because of = () => { var metakeywords = page.MetaKeywords; };

        It should_lazy_load = () => loader.Received().Load(page);
    }

    [Subject(typeof(LazyPage))]
    public class when_page_meta_keywords_is_set : LazyPageSpec
    {
        Establish context = () =>
        {
            page.MetaKeywords = "Blog, CMS, ASP.NET MVC, Flat file, Git";
            loader.ClearReceivedCalls();
        };

        Because of = () => { var metakeywords = page.MetaKeywords; };

        It should_not_lazy_load = () => loader.DidNotReceive().Load(page);
    }

    [Subject(typeof(LazyPage))]
    public class when_page_meta_description_is_accessed_for_first_time :
        LazyPageSpec
    {
        Because of = () => { var metadescription = page.MetaDescription; };

        It should_lazy_load = () => loader.Received().Load(page);
    }

    [Subject(typeof(LazyPage))]
    public class when_page_meta_description_is_set : LazyPageSpec
    {
        Establish context = () =>
        {
            page.MetaDescription = "This page summarize what is new in " +
                                   "classy blog.";

            loader.ClearReceivedCalls();
        };

        Because of = () => { var metadescription = page.MetaDescription; };

        It should_not_lazy_load = () => loader.DidNotReceive().Load(page);
    }

    [Subject(typeof(LazyPage))]
    public class when_page_author_is_accessed_for_first_time : LazyPageSpec
    {
        Because of = () => { var author = page.Author; };

        It should_lazy_load = () => loader.Received().Load(page);
    }

    [Subject(typeof(LazyPage))]
    public class when_page_author_is_set : LazyPageSpec
    {
        Establish context = () =>
        {
            page.Author = "Kazi Manzur Rashid";
            loader.ClearReceivedCalls();
        };

        Because of = () => { var author = page.Author; };

        It should_not_lazy_load = () => loader.DidNotReceive().Load(page);
    }

    [Subject(typeof(LazyPage))]
    public class when_page_allow_comments_is_accessed_for_first_time :
        LazyPageSpec
    {
        Because of = () => { var allowComments = page.AllowComments; };

        It should_lazy_load = () => loader.Received().Load(page);
    }

    [Subject(typeof(LazyPage))]
    public class when_page_allow_comment_is_true : LazyPageSpec
    {
        Establish context = () =>
        {
            page.AllowComments = true;
            loader.ClearReceivedCalls();
        };

        Because of = () => { var allowComments = page.AllowComments; };

        It should_not_lazy_load = () => loader.DidNotReceive().Load(page);
    }

    [Subject(typeof(LazyPage))]
    public class when_page_body_is_accessed_for_first_time : LazyPageSpec
    {
        Because of = () => { var body = page.Body; };

        It should_lazy_load = () => loader.Received().Load(page);
    }

    [Subject(typeof(LazyPost))]
    public class when_page_body_is_set : LazyPageSpec
    {
        Establish context = () =>
        {
            page.Body = "This is the body of the page.";
            loader.ClearReceivedCalls();
        };

        Because of = () => { var body = page.Body; };

        It should_not_lazy_load = () => loader.DidNotReceive().Load(page);
    }
}